/**
 * @Copyright:Copyright (c) 1992 - 2016
 * @Company: TengTong
 */

package com.tengtong.duang.commons.base;

import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import com.tengtong.duang.commons.base.impl.SimpleResult;

/**
 * 通用的返回结果接口
 * 
 * @author Jai
 *
 */
public interface Result<T> {
	
	/**
	 * 一个空的返回结果
	 */
	public static <T> Result<T> empty(){
		return new SimpleResult<>();
	}

	/**
	 * 如果 isSuccess == true 就执行命令
	 * 
	 * @param consumer
	 */
	default public void ifSuccess(Command command){
		if(isSuccess()){
			command.execute();
		}
	}
	
	/**
	 * 如果里面的值 v 不是 null 的话，执行 consumer 
	 * 
	 * @param consumer
	 */
    default public void ifPresent(Consumer<? super T> consumer) {
        if (getValue() != null)
            consumer.accept(getValue());
    }
	
	/**
	 * 如果里面的值 v 不是 null 的话，并且 isSuccess() 为真，执行 consumer 
	 * 
	 * @param consumer
	 */
    default public void ifSuccessPresent(Consumer<? super T> consumer) {
        if (isPresent())
            consumer.accept(getValue());
    }
        
	/**
	 * 如果里面的 exception 不是 null 的话，执行 consumer。注意， Consumer 的参数传入 Result 本身 
	 * 
	 * @param consumer
	 */
    default public void ifExcepton(Consumer<Result<T>> consumer) {
        if (getException() != null)
            consumer.accept(this);
    }
   
    /**
     * 可以对 Result 里面的值进行某种过滤或检查动作（predicate），如果符合条件就返回自身，如果不符合就返回一个空值
     * 
     * EMPTY
     * 
     * @param predicate
     * @return
     */
    default public Result<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        if (!isPresent())
            return this;
        else
            return predicate.test(getValue()) ? this : empty();
    }

    /**
     * 对 结果的值进行 处理（例如转换），返回一个新的结果。。。
     * 
     * @param mapper
     * @return
     */
    default public<U> Result<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return SimpleResult.ofNullable(mapper.apply(getValue()));
        }
    }
    
	/**
     * isSuccess() 为真，同时 getValue() != null 时返回真
     * 
     * @return
     */
    default public boolean isPresent() {
        return isSuccess() && (getValue() != null);
    }
    
    /**
     * 如果有值就返回值，如果没有就返回 other
     * @param other
     * @return
     */
    default public T orElse(T other){
    	return this.getValue() != null?this.getValue():other;
    }
    
    /**
     * 如果有值就返回值，如果没有就返回由 other.get() 返回的值 （可以动态生成值）
     * @param other
     * @return
     */
    default public T orElseGet(Supplier<? extends T> other){
    	return this.getValue() != null?this.getValue(): other.get();
    }
   
    /**
     * 如果有值就返回值，如果没有就抛出由 supplier 所提供的异常
     * 
     * @param exceptionSupplier
     * @return
     * @throws X
     */
    default public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (getValue() != null) {
            return getValue();
        } else {
            throw exceptionSupplier.get();
        }
    }    
    
	/**
	 * 是否成功
	 * 
	 * @return
	 */
	public boolean isSuccess();
	
	/**
	 * 返回的值
	 * 
	 * @return
	 */
	public T getValue();
	
	/**
	 * 返回抛出异常
	 * @return
	 */
	public Throwable getException();
}
